package com.ztrue.framework.core.event.impl;

import com.ztrue.framework.core.event.IDomainEvent;
import com.ztrue.framework.core.event.IEventSerializer;
import com.ztrue.framework.exception.InvalidOperationException;
import com.ztrue.framework.infrastructure.IClassProvider;
import com.ztrue.common.log.Logger;
import com.ztrue.common.serializing.ITextSerializer;

import java.util.*;

/**
 * 默认事件序列化方式
 * 默认使用JSON格式序列化
 *
 * @author zhangw
 * @date 2016/10/27 16:32
 * @version: 1.0
 */
public class DefaultEventSerializer implements IEventSerializer {
    private static final Logger logger = Logger.getLogger(IEventSerializer.class);
    private ITextSerializer serializer;
    private IClassProvider classProvider;

    public DefaultEventSerializer(ITextSerializer jsonSerializer, IClassProvider classProvider) {
        this.serializer = jsonSerializer;
        this.classProvider = classProvider;
    }

    /**
     * 序列化集合
     *
     * @param events
     * @return
     */
    public Map<String, String> serialize(Iterator<IDomainEvent> events) {
        Map<String, String> eventMap = new HashMap<>();
        IDomainEvent event;
        while (events.hasNext()) {
            event = events.next();
            eventMap.put(classProvider.getName(event.getClass()), serializer.serialize(event));
        }
        return eventMap;
    }

    /**
     * 序列化集合
     *
     * @param events
     * @return
     */
    public Map<String, String> serialize(Collection<IDomainEvent> events) {
        return this.serialize(events.iterator());
    }

    /**
     * 反序列化集合
     *
     * @param data
     * @return
     */
    public List<IDomainEvent> deserialize(Map<String, String> data) {
        try {
            Iterator<String> iterator = data.keySet().iterator();
            String key;
            List<IDomainEvent> domainEvents = new ArrayList<>();
            while (iterator.hasNext()) {
                key = iterator.next();
                domainEvents.add((IDomainEvent) serializer.deserialize(data.get(key), classProvider.getClass(key)));
            }
            return domainEvents;
        } catch (Exception e) {
            logger.error("无法反序列化领域事件集合[" + serializer.serialize(data) + "]", e);
            throw new InvalidOperationException("无法反序列化领域事件集合[" + serializer.serialize(data) + "]", e);
        }
    }

    /**
     * 反序列化单个领域事件
     *
     * @param typeName
     * @param data
     * @return
     */
    public IDomainEvent deserialize(String typeName, String data) {
        try {
            return (IDomainEvent) serializer.deserialize(data, classProvider.getClass(typeName));
        } catch (Exception e) {
            logger.error("无法反序列化领域事件[" + data + "]", e);
            throw new InvalidOperationException("无法反序列化领域事件[" + data + "]");
        }
    }
}
